package com.crazy.web.service.user.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.exceptions.ValidateException;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.crazy.model.major.dto.RoleAuthorityDto;
import com.crazy.model.major.dto.RoleDto;
import com.crazy.model.major.dto.UserRoleDto;
import com.crazy.model.major.entity.TRoleLimitRelation;
import com.crazy.model.major.entity.TUserLimit;
import com.crazy.model.major.entity.TUserRole;
import com.crazy.model.major.entity.TUserRoleRelation;
import com.crazy.model.major.service.TRoleLimitRelationService;
import com.crazy.model.major.service.TUserLimitService;
import com.crazy.model.major.service.TUserRoleRelationService;
import com.crazy.model.major.service.TUserRoleService;
import com.crazy.web.service.user.RoleService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author zhaochaofeng
 * @version 1.0
 * @date 2020/12/17 13:36
 */
@Service
public class RoleServiceImpl implements RoleService {

    @Autowired
    private TUserRoleService tUserRoleService;
    @Autowired
    private TUserLimitService tUserLimitService;
    @Autowired
    private TRoleLimitRelationService tRoleLimitRelationService;
    @Autowired
    private TUserRoleRelationService tUserRoleRelationService;

    @Override
    public IPage<TUserRole> list(int page, int rows) {
        QueryWrapper<TUserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(TUserRole.Columns.valid, 1);
        Page<TUserRole> rolePage = new Page<TUserRole>(page, rows);
        IPage<TUserRole> roleIPage = tUserRoleService.page(rolePage, queryWrapper);
        List roles = new ArrayList();
        roleIPage.getRecords().stream().forEach(c -> {
            RoleDto roleDto = new RoleDto();
            BeanUtil.copyProperties(c, roleDto);
            roles.add(roleDto);
        });
        roleIPage.setRecords(roles);
        return roleIPage;
    }

    @Override
    public void delete(Long id) {
        TUserRole role = tUserRoleService.getById(id);
        if(role==null || role.getValid()!=1){
            throw new ValidateException("角色不存在");
        }
        role.setValid(0);
        tUserRoleService.updateById(role);
    }

    @Override
    public List<RoleAuthorityDto> getAuthByRoleId(Long roleId) {
        QueryWrapper<TUserLimit> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(TUserLimit.Columns.valid, 1);
        queryWrapper.orderByAsc(TUserLimit.Columns.level);
        List<TUserLimit> limits = tUserLimitService.list(queryWrapper);
        List<RoleAuthorityDto> roleAuthorityDtos = new ArrayList<>();
        if(roleId==null){
            for(TUserLimit limit : limits){
                RoleAuthorityDto roleAuthorityDto = new RoleAuthorityDto();
                roleAuthorityDto.setId(limit.getId());
                roleAuthorityDto.setPId(limit.getParentId()==null?0:limit.getParentId());
                roleAuthorityDto.setName(limit.getLimitName());
                roleAuthorityDto.setChecked(false);
                roleAuthorityDtos.add(roleAuthorityDto);
            }
            return roleAuthorityDtos;
        }else{
            QueryWrapper<TRoleLimitRelation> queryWrapper1 = new QueryWrapper<>();
            queryWrapper1.eq(TRoleLimitRelation.Columns.roleId, roleId);
            List<TRoleLimitRelation> roleLimitRelations = tRoleLimitRelationService.list(queryWrapper1);
            List<Long> hasLimits = new ArrayList<>();
            for(TRoleLimitRelation roleLimitRelation : roleLimitRelations){
                hasLimits.add(roleLimitRelation.getLimitId());
            }
            for(TUserLimit limit : limits){
                RoleAuthorityDto roleAuthorityDto = new RoleAuthorityDto();
                roleAuthorityDto.setId(limit.getId());
                roleAuthorityDto.setPId(limit.getParentId()==null?0:limit.getParentId());
                roleAuthorityDto.setName(limit.getLimitName());
                if(hasLimits.contains(limit.getId())){
                    roleAuthorityDto.setChecked(true);
                }else{
                    roleAuthorityDto.setChecked(false);
                }
                roleAuthorityDtos.add(roleAuthorityDto);
            }
            return roleAuthorityDtos;
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void saveOrUpdate(TUserRole tUserRole, Long[] auths) {
        if(tUserRole.getId()==null){
            //新增
            tUserRole.setCreateTime(LocalDateTime.now());
            tUserRole.setUpdateTime(LocalDateTime.now());
            tUserRoleService.save(tUserRole);
        }else{
            //修改
            TUserRole oldRole = tUserRoleService.getById(tUserRole.getId());
            oldRole.setRoleName(tUserRole.getRoleName());
            oldRole.setRequireRole(tUserRole.getRequireRole());
            oldRole.setDescript(tUserRole.getDescript());
            oldRole.setUpdateTime(LocalDateTime.now());
            tUserRoleService.updateById(oldRole);
            QueryWrapper<TRoleLimitRelation> queryWrapper = new QueryWrapper<>();
            queryWrapper.eq(TRoleLimitRelation.Columns.roleId, tUserRole.getId());
            tRoleLimitRelationService.remove(queryWrapper);
        }
        List<TRoleLimitRelation> list = new ArrayList<>();
        if(auths!=null)
        {
            for(Long auth : auths) {
                TRoleLimitRelation roleLimitRelation = new TRoleLimitRelation();
                roleLimitRelation.setRoleId(tUserRole.getId());
                roleLimitRelation.setLimitId(auth);
                list.add(roleLimitRelation);
            }
        }
        tRoleLimitRelationService.saveBatch(list);
    }

    @Override
    public List<UserRoleDto> all(Long userId) {
        QueryWrapper<TUserRole> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(TUserRole.Columns.valid, 1);
        List<TUserRole> allRoles = tUserRoleService.list(queryWrapper);

        QueryWrapper<TUserRoleRelation> queryWrapper1 = new QueryWrapper<>();
        queryWrapper1.eq(TUserRoleRelation.Columns.userId, userId);
        List<TUserRoleRelation> userRoleRelations = tUserRoleRelationService.list(queryWrapper1);
        List<Long> roleIds = userRoleRelations.stream().map(TUserRoleRelation::getRoleId).collect(Collectors.toList());

        List<UserRoleDto> userRoleDtos = new ArrayList<>();
        allRoles.stream().forEach(c -> {
            UserRoleDto userRoleDto = new UserRoleDto();
            userRoleDto.setRoleId(c.getId());
            userRoleDto.setRoleName(c.getRoleName());
            if(roleIds.contains(c.getId())){
                userRoleDto.setChecked(true);
            }else {
                userRoleDto.setChecked(false);
            }
            userRoleDtos.add(userRoleDto);
        });
        return userRoleDtos;
    }

    @Override
    public void tieRole(Long userId, Long[] roles) {
        if(roles!=null){
            for(Long role : roles){
                TUserRoleRelation tUserRoleRelation = new TUserRoleRelation();
                tUserRoleRelation.setUserId(userId);
                tUserRoleRelation.setRoleId(role.longValue());
                tUserRoleRelationService.save(tUserRoleRelation);
            }
        }
    }
}
